package com.mq.config;

import jakarta.annotation.Resource;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 死信交换机配置
 */
@Configuration
@ConditionalOnProperty(name = "spring.rabbitmq.listener.simple.retry.enabled", havingValue = "true") // 仅在retry.enabled=true时才加载本配置类
public class ErrorMessageConfig {
    /**
     * 本地测试达到最大重试次数后，消息会被丢弃。这在某些对于消息可靠性要求较高的业务场景下，显然不太合适了。
     * 因此Spring允许我们自定义重试次数耗尽后的消息处理策略，这个策略是由`MessageRecovery`接口来定义的，它有3个不同实现：
     * -  `RejectAndDontRequeueRecoverer`：重试耗尽后，直接`reject`，丢弃消息。默认就是这种方式
     * -  `ImmediateRequeueMessageRecoverer`：重试耗尽后，返回`nack`，消息重新入队
     * -  `RepublishMessageRecoverer`：重试耗尽后，将失败消息投递到指定的交换机
     *
     * 比较优雅的一种处理方案是`RepublishMessageRecoverer`，失败后将消息投递到一个指定的，**专门存放异常消息的队列**，后续由人工集中处理。
     */
    //定义处理失败消息的交换机和队列
    @Bean
    public DirectExchange errorMessageExchange(){
        return new DirectExchange("error.direct", true, false);
    }
    @Bean
    public Queue errorMessageQueue(){
        return new Queue("error.queue", true);
    }
    @Bean
    public Binding bindingErrorMessageQueue(){
        return BindingBuilder.bind(errorMessageQueue()).to(errorMessageExchange()).with("error");
    }
    // 定义消息本地重试耗尽后的处理策略
//    @Bean
//    public MessageRecoverer republishMessageRecoverer(RabbitTemplate rabbitTemplate){
//        return new RepublishMessageRecoverer(rabbitTemplate,"error.direct", "error");
//    }
}
